1 module hip.gui.screen; 2 public import hip.gui.widget; 3 import hip.api.input.button; 4 import std.internal.digest.sha_SSSE3; 5 6 /** 7 * Screen is where all widgets should be contained. 8 * This way, the event methods are forwarded correctly, there can exist a drag and drop. 9 * Render order by stack is also possible 10 */ 11 class Screen : Widget 12 { 13 protected Widget focusedWidget; 14 protected Widget draggedWidget; 15 private Widget widgetHolded; 16 private Widget widgetMouseEntered; 17 18 19 this(){setupEvents();} 20 21 private const(HipButton)* mouseDownEv, mouseUpEv; 22 private const(ScrollListener)* scrollEv; 23 private const(TouchMoveListener)* moveEv; 24 25 26 27 final void setupEvents() 28 { 29 import hip.api:HipInput, HipMouseButton; 30 mouseDownEv = HipInput.addTouchListener(HipMouseButton.left, 31 (const AHipButtonMetadata meta) 32 { 33 handleMouseDown(); 34 }); 35 36 mouseUpEv = HipInput.addTouchListener(HipMouseButton.left, 37 (const(AHipButtonMetadata) meta) 38 { 39 stopDragging(); 40 handleMouseUp(); 41 }, HipButtonType.up); 42 43 moveEv = HipInput.addTouchMoveListener((int x, int y) 44 { 45 handleMouseEnter(x, y); 46 startDragging(x, y); 47 }); 48 49 scrollEv = HipInput.addScrollListener((float[3] scroll) 50 { 51 handleScroll(scroll); 52 }); 53 } 54 55 56 int findWidget(Widget w) 57 { 58 for(int i = 0; i < children.length; i++) 59 if(children[i] is w) return i; 60 return -1; 61 } 62 63 private void handleMouseDown() 64 { 65 import hip.api; 66 67 Widget w = findWidgetAt(HipInput.getWorldTouchPosition()); 68 widgetHolded = w; 69 setFocusOn(w); 70 if(w !is null) w.onMouseDown(); 71 } 72 private void handleMouseUp() 73 { 74 import hip.api; 75 if(widgetHolded !is null) 76 { 77 widgetHolded.onMouseUp(); 78 if(findWidgetAt(HipInput.getWorldTouchPosition()) is widgetHolded) 79 widgetHolded.onMouseClick(); 80 } 81 widgetHolded = null; 82 } 83 private void handleScroll(float[3] scroll) 84 { 85 import hip.api; 86 Widget w = findWidgetAt(HipInput.getWorldTouchPosition()); 87 setFocusOn(w); 88 if(w !is null) 89 { 90 import hip.gui.scroll_area; 91 IRawScrollable scrollable = cast(IRawScrollable)w; 92 if(scrollable !is null) scrollable.onRawScroll(scroll); 93 } 94 } 95 96 private void handleMouseEnter(int x, int y) 97 { 98 Widget mEnterWidget = findWidgetAt(x, y); 99 if(widgetMouseEntered !is mEnterWidget) 100 { 101 if(widgetMouseEntered) 102 widgetMouseEntered.onMouseExit(); 103 if(mEnterWidget) 104 mEnterWidget.onMouseEnter(); 105 } 106 widgetMouseEntered = mEnterWidget; 107 } 108 private void startDragging(int x, int y) 109 { 110 if(widgetHolded && !draggedWidget) 111 { 112 setDragging(widgetHolded, x , y); 113 } 114 if(draggedWidget !is null) 115 draggedWidget.onDragged(x, y); 116 } 117 118 private void pushToTop(Widget w) 119 { 120 int pos = findWidget(w); 121 if(pos == children.length-1) return; 122 else if(pos != -1) 123 { 124 import hip.api; 125 import hip.util.algorithm; 126 children[pos+1..$].copyInto(children[pos..$-1]); 127 children[$-1] = w; 128 } 129 } 130 131 void setFocusOn(Widget w) 132 { 133 if(focusedWidget is w) return; 134 if(focusedWidget !is null) 135 focusedWidget.onFocusExit(); 136 focusedWidget = w; 137 if(w !is null) 138 { 139 pushToTop(w); 140 w.onFocusEnter(); 141 } 142 } 143 144 void setDragging(Widget w, int x, int y) 145 { 146 if(w !is null && w.isDraggable) 147 { 148 w.onDragStart(x, y); 149 draggedWidget = w; 150 } 151 } 152 153 void stopDragging() 154 { 155 if(draggedWidget !is null) 156 { 157 draggedWidget.onDragEnd(); 158 draggedWidget = null; 159 } 160 } 161 162 }